package com.app.util.db;

import java.sql.Connection;
import java.sql.SQLException;

import com.app.util.pool.CloseObjectHandler;
import com.app.util.pool.NewObjectException;
import com.app.util.pool.NewObjectHandler;
import com.app.util.pool.ObjectPool;
import com.app.util.pool.PoolConfig;

/**
 * 数据库连接池
 * 
 * @author yaoming
 */
public class DBPool {

	private ObjectPool<Connection> pool;
	private PoolConf poolConf;

	/**
	 * 构造一个数据库连接池
	 * 
	 * @param conf
	 * @throws SQLException
	 * @throws NewObjectException 
	 */
	public DBPool(PoolConf poolConf) throws SQLException, NewObjectException {
		this.poolConf = poolConf;
		final ConnectionCreater connectionCreater = new ConnectionCreater(poolConf.getDriver(), poolConf.getUrl(), poolConf.getUser(), poolConf.getPassword());
		final PoolConfig<Connection> pc = new PoolConfig<Connection>(new NewObjectHandler<Connection>() {
			public Connection newObject() throws NewObjectException {
				try {
					return connectionCreater.newConnection();
				} catch (Exception e) {
					throw new NewObjectException(e);
				}
			}
		});
		pc.setCloseObjectHandler(new CloseObjectHandler<Connection>() {
			public void closeObject(Connection obj) {
				try {
					obj.close();
				} catch (Exception e) {
				}
			}
		});
		pc.setCheckTimes(poolConf.getCheckTimes());
		pc.setMaxActive(poolConf.getMaxActive());
		pc.setMaxIdle(poolConf.getMaxIdle());
		pool = new ObjectPool<Connection>(pc);
	}

	/**
	 * 得到一个数据库连接
	 * 
	 * @return
	 * @throws NewObjectException
	 */
	public Connection getConnection() throws NewObjectException, SQLException {
		Connection con = pool.getObject();
		try {
			validCheck(con);
			return con;
		} catch (Exception e) {
			pool.distoryObject(con);
			throw new SQLException("Connection valid check fail.", e);
		}
	}

	private void validCheck(Connection con) throws SQLException {
		if (con.isClosed()) {
			throw new SQLException("Connection has bean closed.");
		}
	}

	/**
	 * 释放链接
	 * 
	 * @param con
	 */
	public void releaseConnection(Connection con) {
		if (null == con)
			return;
		pool.releaseObject(con);
	}

	public PoolConf getPoolConf() {
		return poolConf;
	}
}
